class Publisher {
  constructor(id, name) {
    this.id = id;
    this.name = name;
  }
}

class Subscriber {
  constructor(id, name) {
    this.id = id;
    this.name = name;
  }
  //更新操作
  update(publisher, data) {
    console.log(publisher.name + "发布了新内容：" + data);
  }
}

class PubSub {
  constructor() {
    //事件调度中心
    this.pubsub = {};
  }

  /**
   * @description 发布动作
   * @param {object} publisher 发布者
   * @param {object} data 发布内容
   */
  publish(publisher, data) {
    const subscribers = this.pubsub[publisher.id];
    if (!subscribers || !subscribers.length) return;
    subscribers.forEach((subscriber) => subscriber.update(publisher, data));
  }

  /**
   * @description 订阅动作
   * @param {obejct} publisher 发布者
   * @param {object} subscriber 订阅者
   */
  subscribe(publisher, subscriber) {
    //如果该发布者没有订阅者，则初始化数组
    !this.pubsub[publisher.id] && (this.pubsub[publisher.id] = []);

    //将订阅者对象放进事件调度中心
    this.pubsub[publisher.id].push(subscriber);
  }

  /**
   * @description 取消订阅
   * @param {object} subscriber 订阅者
   * @param {object} publisher 发布者
   */
  unsubscribe(publisher, subscriber) {
    const index = this.pubsub[publisher.id].findIndex(
      (sub) => sub.id === subscriber.id
    );
    if (index !== -1) this.pubsub[publisher.id].splice(index, 1);
  }
}

//简单测试
const wzq = new Subscriber(666, "wzq");
const yxy = new Publisher(99, "Evan You");
const pubSub = new PubSub(); //这里建议使用单例模式创建对象
pubSub.subscribe(yxy, wzq);
pubSub.publish(yxy, "Vue 3.2正式发布");
pubSub.unsubscribe(yxy, wzq);
pubSub.publish(yxy, "Vue 4.0将于2022年1月发布"); //没有输出
